package com.hdb.dao;

import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.*;
import org.springframework.context.ApplicationContext;

/**
 * Created by aszer on 2016/11/6.
 */
@SuppressWarnings("unchecked")
public class Hib<T> {
    private static final String packageName = "com.hdb";
    public static final String TAdmin = "TAdmin";
    public static final String TClassification = "TClassification";
    public static final String TComment = "TComment";
    public static final String TGood = "TGood";
    public static final String TMyOrder = "TMyOrder";
    public static final String TNotice = "TNotice";
    public static final String TOrderGood = "TOrderGood";
    public static final String TUser = "TUser";
    public static final String TTableInfo = "TTableInfo";
    //
    private static SessionFactory sessionFactory;
    private final Log log = LogFactory.getLog(Hib.class);
    private final String tableName;
    public static Session session;

    public Hib(String tableName) {
        this.tableName = tableName;
    }

    public String getTableName() {
        return tableName;
    }

    public T filter(T table) {
        return (T) DataFilter.filterT(table, getTClass());
    }

    public List<T> filter(List<T> table) {
        return DataFilter.filterT(table, getTClass());
    }

    public List<Object[]> filter(List table, Class<?> otherTClass) {
        return DataFilter.filterT((List<Object[]>) table, getTClass(), otherTClass);
    }

    public static Session getSession() {
        return sessionFactory.openSession();
    }

    public Class<?> getTClass() {
        try {
            return Class.forName("com.hdb." + getTableName());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }
/*    public int getDataCount(){
        try {
            com.hdb.TTableInfo instance = (com.hdb.TTableInfo) getSession().get(
                    packageName + ".TTableInfo", tableName);
            return instance.getTableCount();
        } catch (RuntimeException re) {
            log.error("主键查找失败", re);
        }
        return -1;
    }*/
    public boolean save(T transientInstance) {
        boolean res = false;
        Session s = getSession();
        Transaction t = s.beginTransaction();
        try {
            s.save(transientInstance);
            t.commit();
            res = true;
        } catch (RuntimeException re) {
            log.error("保存失败", re);
        } finally {
            s.close();
        }
        return res;
    }

    public boolean delete(T persistentInstance) {
        log.debug("deleting T instance");
        boolean res = false;
        Session s = getSession();
        Transaction t = s.beginTransaction();
        try {
            s.delete(persistentInstance);
            t.commit();
            res = true;
        } catch (RuntimeException re) {
            log.error("删除失败", re);
            t.rollback();
        } finally {
            s.close();
        }
        return res;
    }

    public int delete(String propertyName, Object value) {
        int res = -1;
        Session s = getSession();
        Transaction t = s.beginTransaction();
        try {
            String queryString = "delete from " + tableName + " as model where model."
                    + propertyName + "= ?";
            res = s.createQuery(queryString).setParameter(0, value).executeUpdate();
            t.commit();
        } catch (RuntimeException re) {
            log.error("按条件删除失败", re);
            t.rollback();
        }
        return res;
    }

    public T merge(T detachedInstance) {
        Session s = getSession();
        Transaction t = s.beginTransaction();
        try {
            T result = (T) getSession().merge(
                    detachedInstance);
            t.commit();
            return result;
        } catch (RuntimeException re) {
            log.error("合并失败", re);
            t.rollback();
        } finally {
            s.close();
        }
        return null;
    }

    public boolean attach(T instance) {
        boolean res = false;
        Session s = getSession();
        Transaction t = s.beginTransaction();
        try {
            s.saveOrUpdate(instance);
            t.commit();
            res = true;
        } catch (RuntimeException re) {
            log.error("更新失败", re);
            t.rollback();
        }
        return res;
    }

    public List<T> find(String propertyName, Object value, int start, int length) {
        try {
            String queryString = "from " + tableName + " as model where model."
                    + propertyName + "= ?";
            return filter(getSession()
                    .createQuery(queryString)
                    .setParameter(0, value)
                    .setFirstResult(start)
                    .setMaxResults(length)
                    .list());
        } catch (RuntimeException re) {
            log.error("查找失败", re);
        }
        return null;
    }

    public List<T> findOrderBy(String propertyName, Object value, String orderBy, boolean desc, int start, int length) {
        try {
            String queryString = "from " + tableName + " as model where model."
                    + propertyName + "= ?" + " order by " + orderBy + " " + (desc ? "desc" : "asc");
            return filter(getSession()
                    .createQuery(queryString)
                    .setParameter(0, value)
                    .setFirstResult(start)
                    .setMaxResults(length)
                    .list());
        } catch (RuntimeException re) {
            log.error("查找失败", re);
        }
        return null;
    }

    public List<Object[]> join(Hib table, String propertyName, int start, int length) {
        try {
            String queryString = "from " + tableName + " as model1," + table.getTableName() + " as model2 where model1."
                    + propertyName + "= model2." + propertyName;
            return filter(getSession()
                    .createQuery(queryString)
                    .setFirstResult(start)
                    .setMaxResults(length)
                    .list(), table.getTClass());
        } catch (RuntimeException re) {
            log.error("连接查找失败", re);
        }
        return null;
    }

    public List<Object[]> join(Hib table, String propertyName, String key, Object value, int start, int length) {
        try {
            String queryString = "from " + tableName + " as model1," + table.getTableName() + " as model2 where model1."
                    + propertyName + "= model2." + propertyName + " and model1." + key + "=:val";
            return filter(getSession()
                    .createQuery(queryString)
                    .setParameter("val", value)
                    .setFirstResult(start)
                    .setMaxResults(length)
                    .list(), table.getTClass());
        } catch (RuntimeException re) {
            log.error("连接带条件查找失败", re);
        }
        return null;
    }

    public List<T> search(String propertyName, String value, int start, int length) {
        try {
            String queryString = "from " + tableName + " as model where model."
                    + propertyName + " like '%" + value + "%'";
            return filter(getSession()
                    .createQuery(queryString)
                    .setFirstResult(start)
                    .setMaxResults(length)
                    .list());
        } catch (RuntimeException re) {
            log.error("搜索失败", re);
        }
        return null;
    }

    public T findOne(String propertyName, Object value) {
        try {
            String queryString = "from " + tableName + " as model where model."
                    + propertyName + "= :val";
            List res = filter(getSession()
                    .createQuery(queryString)
                    .setParameter("val", value)
                    .setMaxResults(1)
                    .list());
            return (T) res.get(0);
        } catch (RuntimeException re) {
            log.error("查找第一个失败", re);
        }
        return null;
    }

    public T findById(int id) {
        log.debug("getting instance with id: " + id);
        try {
            T instance = (T) getSession().get(
                    packageName + "." + tableName, id);
            return instance;
        } catch (RuntimeException re) {
            log.error("主键查找失败", re);
        }
        return null;
    }

    public List<T> findAll(int start, int length) {
        try {
            String queryString = "from " + tableName;
            List res = getSession().createQuery(queryString)
                    .setFirstResult(start)
                    .setMaxResults(length)
                    .list();
            return filter(res);
        } catch (RuntimeException re) {
            log.error("查询所有失败", re);
        }
        return null;
    }

    public List<T> findAllOrderBy(String orderBy, boolean desc, int start, int length) {
        try {
            String queryString = "from " + tableName + " order by " + orderBy + " " + (desc ? "desc" : "asc");
            List res = getSession().createQuery(queryString)
                    .setFirstResult(start)
                    .setMaxResults(length)
                    .list();
            return filter(res);
        } catch (RuntimeException re) {
            log.error("查询所有失败", re);
        }
        return null;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }
}
